package com.alibaba.middleware.race.rpc.netty;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.util.Map;
import java.util.concurrent.Semaphore;

import com.alibaba.middleware.race.rpc.async.ResponseCallbackListener;
import com.alibaba.middleware.race.rpc.async.ResponseFuture;
import com.alibaba.middleware.race.rpc.demo.service.RaceDO;
import com.alibaba.middleware.race.rpc.model.InvokeFuture;
import com.alibaba.middleware.race.rpc.model.RpcRequest;
import com.alibaba.middleware.race.rpc.model.RpcResponse;
import com.alibaba.middleware.race.rpc.serializer.RpcDecoder;
import com.alibaba.middleware.race.rpc.serializer.RpcEncoder;

import io.netty.bootstrap.Bootstrap;
import io.netty.channel.Channel;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.util.HashedWheelTimer;
import io.netty.util.Timer;

public class NewNettyRpcConnection extends ChannelInboundHandlerAdapter {
	
	private InetSocketAddress inetAddr;
	public NewNettyRpcConnection(String host, int port) {
		this.inetAddr = new InetSocketAddress(host, port);
	}
	  @Override
	  public void channelActive(ChannelHandlerContext ctx) throws Exception {
		  	RpcRequest req=new RpcRequest();
			req.setClassName("IHello");
			req.setMethodName("sayHello");
		    ctx.writeAndFlush(req);
	  }

	  @Override
	  public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
	    // you can use the Object from Server here
		RpcResponse rep=(RpcResponse)msg;
		RaceDO do2 =(RaceDO)rep.getResult();
		System.out.println(do2.getNum()+" | "+do2.getStr()+" | "+do2.getList().size()+" | "+do2.getList().toString()+do2.getChild().getChildNum()+" |"+do2.getChild().getLongValue()+" | "+do2.getChild().getChars()[0]+" | "+do2.getChild().getChars()[1]+" | "+do2.getChild().getChars()[2]);
	   
	  }

	  @Override
	  public void exceptionCaught(
	      ChannelHandlerContext ctx, Throwable cause) throws Exception {
	    ctx.close();
	  }
	
	
	public void connection() throws Throwable {
		// TODO Auto-generated method stub
		final NewNettyRpcConnection handle=this;
		EventLoopGroup group = new NioEventLoopGroup();
        try {
            Bootstrap bootstrap = new Bootstrap();
            bootstrap.group(group).channel(NioSocketChannel.class)
                .handler(new ChannelInitializer<SocketChannel>() {
                    @Override
                    public void initChannel(SocketChannel channel) throws Exception {
                        channel.pipeline()
                            .addLast(new RpcEncoder(RpcRequest.class))
                            .addLast(new RpcDecoder(RpcResponse.class))
                            .addLast(handle);
                        
                    }
                })
                .option(ChannelOption.SO_KEEPALIVE, true);

	        ChannelFuture future = bootstrap.connect(this.inetAddr).sync();
	        if (!future.awaitUninterruptibly().isSuccess()) {
				throw future.cause();
			}
        }
        finally {
            //group.shutdownGracefully();
        }
	}
}
